import { useRef, useEffect, useState, useMemo } from 'react';
import { Canvas, useFrame, useThree } from '@react-three/fiber';
import { PerspectiveCamera, Trail, Environment } from '@react-three/drei';
import * as THREE from 'three';
import useGameStore from '../context/gameStore';
import { BufferAttribute, BufferGeometry, Color } from 'three'

// 主游戏场景
const GameScene = () => {
  const initGame = useGameStore(state => state.initGame);
  
  // 初始化游戏状态
  useEffect(() => {
    initGame();
  }, [initGame]);
  
  return (
    <Canvas shadows>
      <Environment preset="city" />
      <GameContent />
    </Canvas>
  );
};

// 游戏内容组件
const GameContent = () => {
  const gameStatus = useGameStore(state => state.gameStatus);
  const activeNotes = useGameStore(state => state.activeNotes);
  const hitNotes = useGameStore(state => state.hitNotes);
  const audioPlayer = useGameStore(state => state.audioPlayer);
  const currentTime = useGameStore(state => state.currentTime);
  const updateTime = useGameStore(state => state.updateTime);
  
  // 两个小球的轨道位置
  const [ball1Lane, setBall1Lane] = useState(1);
  const [ball2Lane, setBall2Lane] = useState(2);
  
  // 小球跳跃状态和目标音符
  const [ball1Jumping, setBall1Jumping] = useState(false);
  const [ball2Jumping, setBall2Jumping] = useState(false);
  const [ball1TargetNote, setBall1TargetNote] = useState(null);
  const [ball2TargetNote, setBall2TargetNote] = useState(null);
  
  // 更新游戏时间和音乐同步
  useFrame(() => {
    if (gameStatus === 'playing' && audioPlayer) {
      updateTime(audioPlayer.now());
      
      // 自动跳跃到下一个音符
      if (!ball1Jumping) {
        const nextNote1 = activeNotes.find(note => 
          note.time > currentTime && 
          !hitNotes.includes(note) &&
          (note.lane === 0 || note.lane === 1) // 只检测轨道1和2
        );
        
        if (nextNote1) {
          setBall1Lane(nextNote1.lane);
          setBall1TargetNote(nextNote1);
          setBall1Jumping(true);
        }
      }
      
      if (!ball2Jumping) {
        const nextNote2 = activeNotes.find(note => 
          note.time > currentTime && 
          !hitNotes.includes(note) &&
          (note.lane === 2 || note.lane === 3) // 只检测轨道3和4
        );
        
        if (nextNote2) {
          setBall2Lane(nextNote2.lane);
          setBall2TargetNote(nextNote2);
          setBall2Jumping(true);
        }
      }
    }
  });
  
  return (
    <>
      {/* 摄像机 */}
      <PerspectiveCamera makeDefault fov={60} position={[0, 8, 12]} />
      <CameraController />
      
      {/* 环境光 */}
      <ambientLight intensity={0.5} />
      <directionalLight
        position={[5, 10, 5]}
        intensity={0.8}
        castShadow
      />
      
      {/* 传送带地面 */}
      <MovingGround time={currentTime} />
      
      {/* 轨道 */}
      <Lanes />
      
      {/* 音符 */}
      <Notes notes={activeNotes} hitNotes={hitNotes} time={currentTime} />
      
      {/* 两个小球 */}
      <JumpingBall
        position={getLanePosition(ball1Lane)}
        targetPosition={getLanePosition(ball1Lane)}
        color="#ff3333"
        isJumping={ball1Jumping}
        time={currentTime}
        noteTime={ball1TargetNote?.time || currentTime}
      />
      <JumpingBall
        position={getLanePosition(ball2Lane)}
        targetPosition={getLanePosition(ball2Lane)}
        color="#3333ff"
        isJumping={ball2Jumping}
        time={currentTime}
        noteTime={ball2TargetNote?.time || currentTime}
      />
    </>
  );
};

// 可配置参数
const TRAIL_LENGTH = 200;      // 拖尾最大长度
const BALL_RADIUS = 0.3;       // 小球半径
const TRAIL_SIZE = 0.2;        // 粒子拖尾大小基数
const JUMP_HEIGHT = 1.5;       // 跳跃高度

function TrailBall() {
  const ballRef = useRef()
  const lineRef = useRef()
  
  // 记录位置历史 [x1,y1,z1, x2,y2,z2,...]
  const [positions, setPositions] = useState(() => new Float32Array(TRAIL_LENGTH * 3))

  // 轨迹线几何体 (高性能BufferGeometry)
  const trailGeometry = useMemo(() => {
    const geom = new BufferGeometry()
    geom.setAttribute('position', new BufferAttribute(positions, 3))
    return geom
  }, [])

  // 主动画循环
  useFrame(({ clock }) => {
    // 1. 更新小球运动 (示例: 圆周运动)
    const time = clock.elapsedTime
    const x = Math.sin(time) * 5
    const z = Math.cos(time) * 3
    const y = Math.sin(time * 2) * 2
    ballRef.current.position.set(x, y, z)

    // 2. 更新轨迹位置历史
    const newPositions = new Float32Array(positions)
    newPositions.copyWithin(0, 3) // 左移数组，移除最旧位置
    newPositions.set([x, y, z], (TRAIL_LENGTH - 1) * 3) // 添加最新位置
    setPositions(newPositions)

    // 3. 更新轨迹线几何体
    trailGeometry.attributes.position.needsUpdate = true
  })

  return (
    <group>
      {/* 主球体 */}
      <mesh ref={ballRef}>
        <sphereGeometry args={[BALL_RADIUS]} />
        <meshStandardMaterial color="hotpink" />
      </mesh>

      {/* 方案1: 连续轨迹线 */}
      <line ref={lineRef} geometry={trailGeometry}>
        <lineBasicMaterial 
          color={new Color(TRAIL_COLOR)} 
          linewidth={2} 
          transparent 
          opacity={0.7}
        />
      </line>

      {/* 方案2: 粒子拖尾 (更灵活但性能要求更高) */}
      {Array.from({ length: TRAIL_LENGTH }).map((_, i) => {
        const idx = i * 3
        const opacity = 1 - i / TRAIL_LENGTH
        return (
          <mesh 
            key={i}
            position={[positions[idx], positions[idx+1], positions[idx+2]]}
            scale={(TRAIL_SIZE * opacity) * 0.8}
          >
            <sphereGeometry />
            <meshBasicMaterial 
              color={TRAIL_COLOR} 
              transparent 
              opacity={opacity}
              depthWrite={false} // 提升透明渲染性能
            />
          </mesh>
        )
      })}
    </group>
  )
}

// 获取轨道X坐标
const getLanePosition = (lane) => {
  return (lane - 1.5) * 2;
};

// 传送带地面
const MovingGround = ({ time }) => {
  const meshRef = useRef();
  const groundTexture = useRef(new THREE.TextureLoader().load('/grid.png'));
  
  useEffect(() => {
    if (groundTexture.current) {
      groundTexture.current.wrapS = groundTexture.current.wrapT = THREE.RepeatWrapping;
      groundTexture.current.repeat.set(4, 20);
    }
  }, []);
  
  useFrame(() => {
    if (groundTexture.current) {
      groundTexture.current.offset.y = -time * 0.5;
    }
  });
  
  return (
    <mesh
      ref={meshRef}
      rotation={[-Math.PI / 2, 0, 0]}
      position={[0, -0.1, 0]}
      receiveShadow
    >
      <planeGeometry args={[12, 50]} />
      <meshPhysicalMaterial
        color="#ffffff"
        metalness={0.9}
        roughness={0.1}
        transmission={0.6}
        thickness={0.5}
        transparent
        opacity={0.3}
        envMapIntensity={1}
        clearcoat={1}
        clearcoatRoughness={0.1}
        ior={1.5}
        map={groundTexture.current}
      />
    </mesh>
  );
};

// 四条轨道
const Lanes = () => {
  return (
    <group>
      {[0, 1, 2, 3].map((lane) => (
        <mesh
          key={lane}
          position={[getLanePosition(lane), 0, 0]}
          rotation={[-Math.PI / 2, 0, 0]}
        >
          <planeGeometry args={[1.8, 50]} />
          <meshPhysicalMaterial
            color="#8888ff"
            metalness={0.6}
            roughness={0.2}
            transparent
            opacity={0.1}
            emissive="#4444ff"
            emissiveIntensity={0.2}
          />
        </mesh>
      ))}
    </group>
  );
};

// 音符组
const Notes = ({ notes, hitNotes, time }) => {
  return (
    <group>
      {notes.map((note, index) => (
        <Note
          key={`note-${index}`}
          note={note}
          isHit={hitNotes.includes(note)}
          time={time}
        />
      ))}
    </group>
  );
};

// 单个音符
const Note = ({ note, isHit, time }) => {
  const position = [
    getLanePosition(note.lane),
    0.1,
    -(note.time - time) * 10 // Z轴位置随时间变化
  ];
  
  // 修改可视范围判断，只有已经过去很久的音符才不渲染
  if (position[2] < -50 || position[2] > 50) return null;
  
  return (
    <mesh position={position} rotation={[-Math.PI / 2, 0, 0]}>
      <circleGeometry args={[0.4, 32]} />
      <meshStandardMaterial
        color={isHit ? "#666666" : "#cccccc"}
        emissive={isHit ? "#333333" : "#ffffff"}
        emissiveIntensity={isHit ? 0 : 0.2}
        transparent
        opacity={isHit ? 0.3 : 1}
      />
    </mesh>
  );
};

// 带拖尾的小球
const JumpingBall = ({ position, color, isJumping, targetPosition, time, noteTime }) => {
  const ballRef = useRef();
  const lineRef = useRef();
  const [positions, setPositions] = useState(() => new Float32Array(TRAIL_LENGTH * 3));
  const [currentPos, setCurrentPos] = useState({ x: position, y: 0.5, z: 0 });
  const jumpStartTime = useRef(0);
  const isMoving = useRef(false);
  const jumpDuration = useRef(0.5);

  // 轨迹线几何体
  const trailGeometry = useMemo(() => {
    const geom = new BufferGeometry();
    geom.setAttribute('position', new BufferAttribute(positions, 3));
    return geom;
  }, []);

  // 计算抛物线位置
  const calculateParabola = (start, end, progress) => {
    const x = start.x + (end.x - start.x) * progress;
    const z = start.z + (end.z - start.z) * progress;
    const y = JUMP_HEIGHT * Math.sin(progress * Math.PI);
    return { x, y, z };
  };

  // 主动画循环
  useFrame(({ clock }) => {
    if (isMoving.current) {
      const progress = (clock.elapsedTime - jumpStartTime.current) / jumpDuration.current;
      
      if (progress <= 1) {
        const newPos = calculateParabola(
          { x: position, y: 0.5, z: 0 },
          { x: targetPosition, y: 0.5, z: 0 },
          progress
        );
        setCurrentPos(newPos);
        ballRef.current.position.set(newPos.x, newPos.y, newPos.z);
      } else {
        isMoving.current = false;
        setCurrentPos({ x: targetPosition, y: 0.5, z: 0 });
      }
    }

    // 更新轨迹位置历史
    const newPositions = new Float32Array(positions);
    newPositions.copyWithin(0, 3);
    newPositions.set([currentPos.x, currentPos.y, currentPos.z], (TRAIL_LENGTH - 1) * 3);
    setPositions(newPositions);
    trailGeometry.attributes.position.needsUpdate = true;
  });

  // 开始跳跃
  useEffect(() => {
    if (isJumping && !isMoving.current) {
      isMoving.current = true;
      jumpStartTime.current = time;
      // 根据音符时间间隔调整跳跃持续时间
      jumpDuration.current = Math.min(0.5, noteTime - time);
    }
  }, [isJumping, time, noteTime]);

  return (
    <group>
      {/* 主球体 */}
      <mesh ref={ballRef}>
        <sphereGeometry args={[BALL_RADIUS]} />
        <meshStandardMaterial 
          color={color} 
          emissive={color} 
          emissiveIntensity={1} 
        />
      </mesh>

      {/* 轨迹线 */}
      <line ref={lineRef} geometry={trailGeometry}>
        <lineBasicMaterial 
          color={new Color(color)} 
          linewidth={2} 
          transparent 
          opacity={0.7}
        />
      </line>

      {/* 粒子拖尾 */}
      {Array.from({ length: TRAIL_LENGTH }).map((_, i) => {
        const idx = i * 3;
        const opacity = 1 - i / TRAIL_LENGTH;
        return (
          <mesh 
            key={i}
            position={[positions[idx], positions[idx+1], positions[idx+2]]}
            scale={(TRAIL_SIZE * opacity) * 0.8}
          >
            <sphereGeometry />
            <meshBasicMaterial 
              color={color} 
              transparent 
              opacity={opacity}
              depthWrite={false}
            />
          </mesh>
        );
      })}
    </group>
  );
};

// 摄像机控制器
const CameraController = () => {
  const { camera } = useThree();
  const targetX = useRef(0);
  const targetY = useRef(8);
  const targetZ = useRef(12);
  
  useFrame(() => {
    // 平滑跟随目标位置
    camera.position.x = THREE.MathUtils.lerp(camera.position.x, targetX.current, 0.1);
    camera.position.y = THREE.MathUtils.lerp(camera.position.y, targetY.current, 0.1);
    camera.position.z = THREE.MathUtils.lerp(camera.position.z, targetZ.current, 0.1);
    
    // 始终看向前方
    camera.lookAt(0, 0, -10);
  });
  
  // 更新相机目标位置
  const updateTarget = (x, y, z) => {
    targetX.current = x;
    targetY.current = y;
    targetZ.current = z;
  };
  
  return null;
};

export default GameScene;
